package org.zkoss.zktc.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Map.Entry;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.zkoss.zktc.core.widget.WidgetDriver;
import org.zkoss.zktc.core.widget.impl.WidgetDriverImpl;

public class DriverLoader {

	static Properties defaultConfig;
	
	static {
		defaultConfig = new Properties();
		InputStream is = DriverLoader.class.getResourceAsStream("/zktc-default.properties");
		if(is!=null){
			try{
				defaultConfig.load(is);
			} catch (IOException e) {
				throw new RuntimeException(e.getMessage(),e);
			}finally{
				try {
					is.close();
				} catch (IOException e) {}
			}
		}
		//config system property
		final String s = "zktc.system.property.";
		for(Entry e:defaultConfig.entrySet()){
			String k = e.getKey().toString();
			if(k.startsWith(s) && k.length()>s.length()){
				System.setProperty(k.substring(s.length()),e.getValue().toString());
			}
		}
	}
	
	public static Properties cloneDefaultConfig(){
		return (Properties)defaultConfig.clone();
	}
	
	public static Properties loadConfig(String name){
		Properties config = null;
		InputStream is = null;
		
		File f = new File(name);
		try{
			if(f.isFile()){
				is = new FileInputStream(f);
			}
			if(is==null){
				is = DriverLoader.class.getResourceAsStream("/"+name);//from package root
			}
			if(is==null){
				return null;
			}
		}catch(Exception e){
			throw new RuntimeException(e.getMessage(),e);
		}

		try {
			config = cloneDefaultConfig();
			config.load(is);
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				is.close();
			} catch (IOException e) {
			}
		}
		return config;
	}
	
	public static WebDriver loadWebDriver(){
		return loadWebDriver(defaultConfig);
	}
	public static WebDriver loadWebDriver(Properties config){
		String browser = config.getProperty("zktc.browser");
		if("firefox".equals(browser)){
			return loadFirefoxWebDriver(config);
		}else if("chrome".equals(browser)){
			return loadChromeWebDriver(config);
		}else if("ie".equals(browser)){
			return loadIEWebDriver(config);
		}else{
			throw new UnsupportedOperationException("type "+browser+" is not supported yet");
		}
		
	}
	
	private static WebDriver loadFirefoxWebDriver(Properties config) {
		String b = config.getProperty("zktc.firefox.binary");
		String p = config.getProperty("zktc.firefox.profile");
		FirefoxBinary fb = null;
		
		if(b==null){
			fb = new FirefoxBinary();
		}else{
			fb = new FirefoxBinary(new File(b));
		}
		
		FirefoxProfile fp = null;
		if(p==null){
			fp = new FirefoxProfile();
		}else{
			fp = new FirefoxProfile(new File(p));//set profile
		}
		//http://code.google.com/p/selenium/issues/detail?id=368
		//not sure it is safe to call it here
		try{
			fp.setEnableNativeEvents(true);
		}catch(Throwable t){
			//TODO log
		}
		return new FirefoxDriver(fb,fp);
	}
	
	private static WebDriver loadChromeWebDriver(Properties config) {
		return new ChromeDriver();
	}
	private static WebDriver loadIEWebDriver(Properties config) {
		return new InternetExplorerDriver();
	}
	

	public static WidgetDriver loadWidgetDrvier(){
		return loadWidgetDrvier(defaultConfig);
	}
	public static WidgetDriver loadWidgetDrvier(Properties config){
		long timeout = Long.parseLong(config.getProperty("zktc.tripTimeout","2000"));
		boolean autoReattach = Boolean.parseBoolean(config.getProperty("zktc.autoReattach","true"));
		return new WidgetDriverImpl(loadWebDriver(config),timeout,autoReattach);
	}
}
